package org.fastsyncer.manager.increment.logmnr;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.fastsyncer.common.constant.MappingConstant;
import org.fastsyncer.common.entity.DatabaseConfig;
import org.fastsyncer.common.entity.MappingTask;
import org.fastsyncer.connector.util.DatabaseUtil;
import org.fastsyncer.manager.store.DataCenter;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

public class LogmnrFactory {

	private static Logger logger = LoggerFactory.getLogger(LogmnrFactory.class);

	private static LogmnrFactory instance = new LogmnrFactory();

	private LogmnrFactory() {
	}

	public static LogmnrFactory getInstance() {
		return instance;
	}

	public JSONArray pull(Map<String, String> params) throws Exception {
		// 获取对应的映射
		String taskName = params.get("taskName");
		MappingTask task = (MappingTask) DataCenter.getInstance().getMapping(taskName);

		DatabaseConfig cfg = new DatabaseConfig();
		BeanUtils.copyProperties(cfg, (DatabaseConfig) task.getSourceMapping().getConfig());

		// 设置登录用户名以DBA身份
		// cfg.setUsername(cfg.getUsername() + " AS SYSDBA");
		JdbcTemplate jdbcTemplate = DatabaseUtil.getJdbcTemplate(cfg);

		// 是否扫描所有日志
		boolean scanAll = false;
		try {
			scanAll = Boolean.valueOf(params.get("scanAll"));
		} catch (Exception e) {
			e.printStackTrace();
		}

		// 日志字典
		String dictionary = params.get("dictionary");
		if (StringUtils.isBlank(dictionary)) {
			throw new Exception("缺少字典文件!");
		}

		// 扫描表
		String table = cfg.getTable();
		if (StringUtils.isBlank(table)) {
			throw new Exception("缺少扫描表!");
		}

		// 最后一次扫描日志位移点
		String scnStart = params.get("scnPos");
		// 标记为第一次扫描日志
		boolean scnFirst = false;
		if (StringUtils.isBlank(scnStart)) {
			logger.info("正在查询最近一次记录点");
			Object maxScn = LogmnrUtil.parseMaxScn(jdbcTemplate, dictionary, scnStart);
			scnStart = maxScn == null ? "0" : maxScn.toString();
			scnFirst = true;
		}

		// 抽取增量日志
		JSONObject parse = null;
		try {
			parse = LogmnrUtil.parse(jdbcTemplate, table, scanAll, dictionary, scnStart);
		} catch (Exception e) {
			// 防止记录点不正确，设置为null,下一次去查询最近一次记录点
			// HashMap<String, String> po =
			// task.getPolicy().get(MappingConstant.POLICY_INCREMENT);
			// po.put("scnPos", null);
			// // 持久化记录点
			// DataCenter.getInstance().storeMapping(task.getName(), task);
			return null;
		}
		JSONArray msg = null;
		if (!parse.isNull("msg")) {
			msg = parse.getJSONArray("msg");
		}

		// 记录下一次记录点
		String scnEnd = parse.getString("scn");
		// 如果有变化，就更新记录点
		boolean logChanged = StringUtils.isNotBlank(scnEnd) && !StringUtils.equals("0", scnEnd);
		// 如果是第一次加载，并且日志无变化，就将scnStart作为最后一次记录点
		scnEnd = scnFirst && !logChanged ? scnStart : scnEnd;

		if (logChanged || scnFirst) {
			// 更新记录点
			HashMap<String, String> po = task.getPolicy().get(MappingConstant.POLICY_INCREMENT);
			po.put("scnPos", (Integer.parseInt(scnEnd) + 1) + "");
			// 持久化记录点
			DataCenter.getInstance().storeMapping(task.getName(), task);
		}

		// 关闭连接
		if (jdbcTemplate != null) {
			jdbcTemplate.getDataSource().getConnection().close();
		}
		return msg;
	}

}
